#pragma once
#include "field.hpp"
#include "tool.hpp"
#include "message.hpp"
#include "net.hpp"
#include <unordered_map>
#include <mutex>

// using MessageCallback = std::function<void(const BaseConnection::Ptr &, BaseMessage::Ptr &)>;

namespace RPC
{
    class CallBack
    {
    public:
        using Ptr = std::shared_ptr<CallBack>;
        virtual void onMessage(const BaseConnection::Ptr &conn, BaseMessage::Ptr &msg) = 0;
    };

    template <class T>
    class CallBackT : public CallBack
    {
    public:
        using Ptr = std::shared_ptr<CallBackT<T>>;
        using MsgCallback =std::function<void(const BaseConnection::Ptr &, std::shared_ptr<T>& )>;

        CallBackT(MsgCallback handler) : _handler(handler) {}
        void onMessage(const BaseConnection::Ptr &conn, BaseMessage::Ptr &msg)
        {
            auto type_msg = std::dynamic_pointer_cast<T>(msg);
            // ERROR_LOG("准备执行定义的方法！");
            _handler(conn, type_msg);
        }

    private:
        MsgCallback _handler;
    };
    class Dispatcher
    {
    public:
        using Ptr = std::shared_ptr<Dispatcher>;

        template <class T>
        void registerCallback(const MType &type, const typename CallBackT<T>::MsgCallback &handler)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            if (_callbacks.count(type))
            {
                ERROR_LOG("该回调函数已经注册过了！");
                return;
            }
            auto cb = std::make_shared<CallBackT<T>>(handler);

            _callbacks.insert({type, cb});
            // DEBUG_LOG("回调函数组测成功！");
        }

        void onMessage(const BaseConnection::Ptr &conn, BaseMessage::Ptr &msg)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            MType type = msg->type();
            INFO_LOG("%s", mType(type).c_str());
            if (_callbacks.count(type))
            {
                // ERROR_LOG("准备调用函数！");
                _callbacks[type]->onMessage(conn, msg);
                return;
            }
            ERROR_LOG("当前没有注册这个回调函数！");
        }

    private:
        std::mutex _mutex;
        std::unordered_map<MType, CallBack::Ptr> _callbacks;
    };
}
